using System;
using System.IO;
using System.Text;
using Update.Utils.Interfaces;

namespace Update.Utils.Logging
{
    /// <summary>
    /// 日志记录辅助类
    /// </summary>
    public class LogHelper : ILogHelper
    {
        private static readonly object _lock = new object();
        private string _logFilePath;
        private bool _enableConsole;
        private LogLevel _minLevel;
        private bool _isEnabled;

        /// <summary>
        /// 创建日志帮助类实例
        /// </summary>
        /// <param name="logFilePath">日志文件路径，为空则仅输出到控制台</param>
        /// <param name="enableConsole">是否在控制台输出日志</param>
        /// <param name="minLevel">最小日志级别</param>
        public LogHelper(string logFilePath = null, bool enableConsole = true, LogLevel minLevel = LogLevel.Debug)
        {
            _logFilePath = logFilePath;
            _enableConsole = enableConsole;
            _minLevel = minLevel;
            _isEnabled = true;

            if (!string.IsNullOrEmpty(_logFilePath))
            {
                // 确保日志目录存在
                string logDir = Path.GetDirectoryName(_logFilePath);
                if (!string.IsNullOrEmpty(logDir) && !Directory.Exists(logDir))
                {
                    Directory.CreateDirectory(logDir);
                }
            }
        }

        /// <summary>
        /// 设置日志文件路径
        /// </summary>
        /// <param name="logFilePath">日志文件路径</param>
        public void SetLogFilePath(string logFilePath)
        {
            _logFilePath = logFilePath;
            if (!string.IsNullOrEmpty(_logFilePath))
            {
                string logDir = Path.GetDirectoryName(_logFilePath);
                if (!string.IsNullOrEmpty(logDir) && !Directory.Exists(logDir))
                {
                    Directory.CreateDirectory(logDir);
                }
            }
        }

        /// <summary>
        /// 启用或禁用日志记录
        /// </summary>
        /// <param name="enabled">是否启用</param>
        public void SetEnabled(bool enabled)
        {
            _isEnabled = enabled;
        }

        /// <summary>
        /// 记录调试级别日志
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="args">格式化参数</param>
        public void Debug(string message, params object[] args)
        {
            Log(LogLevel.Debug, message, args);
        }

        /// <summary>
        /// 记录信息级别日志
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="args">格式化参数</param>
        public void Info(string message, params object[] args)
        {
            Log(LogLevel.Info, message, args);
        }

        /// <summary>
        /// 记录警告级别日志
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="args">格式化参数</param>
        public void Warning(string message, params object[] args)
        {
            Log(LogLevel.Warning, message, args);
        }

        /// <summary>
        /// 记录错误级别日志
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="args">格式化参数</param>
        public void Error(string message, params object[] args)
        {
            Log(LogLevel.Error, message, args);
        }

        /// <summary>
        /// 记录错误日志
        /// </summary>
        /// <param name="ex">异常对象</param>
        /// <param name="message">附加消息</param>
        /// <param name="args">格式化参数</param>
        public void Error(Exception ex, string message = null, params object[] args)
        {
            string exMessage = ex.ToString();
            if (!string.IsNullOrEmpty(message))
            {
                string formattedMessage = args != null && args.Length > 0 ? string.Format(message, args) : message;
                exMessage = $"{formattedMessage}\r\n{exMessage}";
            }
            Log(LogLevel.Error, exMessage);
        }

        /// <summary>
        /// 记录致命错误日志
        /// </summary>
        /// <param name="message">日志消息</param>
        /// <param name="args">格式化参数</param>
        public void Fatal(string message, params object[] args)
        {
            Log(LogLevel.Fatal, message, args);
        }

        /// <summary>
        /// 记录日志
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <param name="message">日志消息</param>
        /// <param name="args">格式化参数</param>
        private void Log(LogLevel level, string message, params object[] args)
        {
            if (!_isEnabled || level < _minLevel)
            {
                return;
            }

            try
            {
                string formattedMessage = args != null && args.Length > 0 ? string.Format(message, args) : message;
                string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{level}] {formattedMessage}";

                // 控制台输出
                if (_enableConsole)
                {
                    ConsoleColor originalColor = Console.ForegroundColor;
                    Console.ForegroundColor = GetConsoleColorForLevel(level);
                    Console.WriteLine(logEntry);
                    Console.ForegroundColor = originalColor;
                }

                // 文件输出
                if (!string.IsNullOrEmpty(_logFilePath))
                {
                    lock (_lock)
                    {
                        try
                        {
                            File.AppendAllText(_logFilePath, logEntry + Environment.NewLine, Encoding.UTF8);
                        }
                        catch
                        {
                            // 写入日志文件失败，忽略错误以避免循环记录日志
                        }
                    }
                }
            }
            catch
            {
                // 忽略所有日志记录过程中的错误
            }
        }

        /// <summary>
        /// 根据日志级别获取控制台颜色
        /// </summary>
        /// <param name="level">日志级别</param>
        /// <returns>控制台颜色</returns>
        private ConsoleColor GetConsoleColorForLevel(LogLevel level)
        {
            switch (level)
            {
                case LogLevel.Debug:
                    return ConsoleColor.Gray;
                case LogLevel.Info:
                    return ConsoleColor.White;
                case LogLevel.Warning:
                    return ConsoleColor.Yellow;
                case LogLevel.Error:
                    return ConsoleColor.Red;
                case LogLevel.Fatal:
                    return ConsoleColor.DarkRed;
                default:
                    return ConsoleColor.Gray;
            }
        }
    }
} 